#pragma once
#include "cond.hpp"
#include "logger.hpp"
#include "mutex.hpp"
#include "thread.hpp"
#include "task.hpp"
#include <queue>
#include <vector>
namespace thread_pool_module
{
    using namespace cond_module;
    using namespace logger_module;
    using namespace mutex_module;
    using namespace thread_module;
    static const int defaultsize =5;
    template <class T>
    class thread_pool
    {
    private:
        thread_pool(int size = defaultsize)
            : _isrunning(false)
        //_taskq(taskq)
        {
            for (int i = 0; i < size; i++)
            {
                _thread_pool.emplace_back([this]()
                                          { handle(); });
            }
        }

    public:
        static thread_pool<T> *get_instance()
        {
            if (ptp == nullptr)
            {
                lock_guard lg(s_mutex);
                LOG(log_level::INFO) << "创建线程池";
                ptp = new thread_pool<T>();
                ptp->start();
            }
            LOG(log_level::INFO) << "获取单例";
            return ptp;
        }
        void stop()
        {
            lock_guard lg(_mutex);
            if(_isrunning)
            {
            _isrunning=false;
            _cond.broadcast();
            }
        }
        void equeue(const T& in)
        {
            // _mutex.lock();
            // _taskq.push(in);
            // _cond.wake();
            // _mutex.unlock();
            if(_isrunning)
            {
                lock_guard lg(_mutex);
                _taskq.push(in);
                _cond.wake();
            }
        }
        void start()
        {
            _isrunning=true;
            for(auto&x:_thread_pool)
            {
                x.start();
                //LOG(log_level::INFO)<<"线程启动了";
            }
            
        }
        void join()
        {
            for (auto &x : _thread_pool)
            {
                x.join(); // 等待所有线程完成
            }
        }
        void detach()
        {
            for(auto&x:_thread_pool)
            {
                x.detach();
            }
        }
        void handle()
        {
            T task;
            char name[128];
            pthread_getname_np(pthread_self(), name, sizeof(name));
            while (true)
            {
            lock_guard lg(_mutex);
            {
            while(_taskq.empty()&&_isrunning)
            {
                _cond.wait(_mutex);
            }
            if(_taskq.empty()&&!_isrunning)
            {
                //一定要解锁不然就死锁了 所以还是lock_guard好用点 因为会自动释放
                LOG(log_level::INFO)<<name<<"线程退出了";
          
                break;
            }
            //一定有任务
            task=_taskq.front();
            _taskq.pop();
            //LOG(log_level::INFO)<<name<<"线程处理任务";
            //任务处理过程中,不需要放在临时区里面
            }
            if(task)    task();
            }
        }
        void wake()
        {
            _cond.wake();
        }
    private:
    std::queue<T> _taskq;
    std::vector<thread> _thread_pool;
    cond _cond;
    mutex _mutex;
    bool _isrunning;
    static thread_pool<T>* ptp;
    static mutex s_mutex;
    };
    template<class T>
    thread_pool<T>* thread_pool<T>::ptp =nullptr;
    template<class T>
    mutex thread_pool<T>::s_mutex; 
}